﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace ExpressTreeDemo
{
    public static class Extensions
    {
        #region 下拉
        /// <summary>
        /// 查询数据源，并转化成SelectListItem列表
        /// </summary>
        /// <typeparam name="T">数据源类型</typeparam>
        /// <param name="baseQuery">基础查询</param>
        /// <param name="wtmcontext">Wtm Context</param>
        /// <param name="textField">SelectListItem中Text字段对应的值</param>
        /// <param name="valueField">SelectListItem中Value字段对应的值，默认为Id列</param>
        /// <param name="ignorDataPrivilege">忽略数据权限判断</param>
        /// <param name="SortByName">是否根据Text字段排序，默认为是</param>
        /// <returns>SelectListItem列表</returns>
        public static IQueryable<ComboSelectListItem> GetSelectListItems<T>(this IQueryable<T> baseQuery
            , Expression<Func<T, string>> textField
            , Expression<Func<T, object>> valueField)
        {
            var query = baseQuery;

            //定义PE
            ParameterExpression pe = Expression.Parameter(typeof(T));
            ChangePara cp = new ChangePara();
            //创建新类，形成类似 new ComboSelectListItem() 的表达式
            NewExpression newItem = Expression.New(typeof(ComboSelectListItem));

            //绑定Text字段，形成类似 Text = textField 的表达式
            var textMI = typeof(ComboSelectListItem).GetMember("Text")[0];
            MemberBinding textBind = Expression.Bind(textMI, cp.Change(textField.Body, pe));


            //绑定Value字段，形成类似 Value = valueField 的表达式
            var valueMI = typeof(ComboSelectListItem).GetMember("Value")[0];
            MemberBinding valueBind = Expression.Bind(valueMI, cp.Change(valueField.Body, pe));

            //合并创建新类和绑定字段的表达式，形成类似 new ComboSelectListItem{ Text = textField, Value = valueField} 的表达式
            MemberInitExpression init = Expression.MemberInit(newItem, textBind, valueBind);

            //将最终形成的表达式转化为Lambda，形成类似 x=> new ComboSelectListItem { Text = x.textField, Value = x.valueField} 的表达式
            var lambda = Expression.Lambda<Func<T, ComboSelectListItem>>(init, pe);


            IQueryable<ComboSelectListItem> rv = null;
            rv = query.Select(lambda);

            return rv;
        }

        #endregion

    }

    public class ComboSelectListItem
    {
        public string Text { get; set; }

        public object Value { get; set; }
    }
}
